Skip to content

Conversation

@wilinz
Copy link

@wilinz wilinz commented Feb 7, 2026

No description provided.

@damacus
Copy link
Owner

damacus commented Feb 8, 2026

Thanks 👍

Can you provide a quick screenshot of the new functionality please

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds bucket policy support across the UI and backend so users can view and set bucket access policies (private / public-read / public-read-write / custom), and exposes policy status in bucket listings and the object browser.

Changes:

  • Add bucket policy view/edit UI (settings card + reusable partial) and policy badges in bucket list/browser.
  • Add MinIO client interface methods + new Echo handlers/routes to get/set bucket policies.
  • Add unit tests for policy JSON canonicalization/type detection and update journey test mocks for new policy lookups.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 10 comments.

Show a summary per file
File Description
views/partials/bucket_policy.html New reusable HTMX/Alpine bucket policy editor fragment.
views/pages/buckets.html Shows a policy-type badge next to each bucket in the list.
views/pages/bucket_settings.html Adds a bucket policy settings section (currently duplicated vs partial).
views/pages/browser.html Adds policy badge/modal and “Direct Link” dialog + copy action.
views/layouts/base.html Removes global HTMX boosted navigation attributes from <body>.
internal/services/minio_factory.go Extends MinioClient with bucket policy methods; exports ShouldUseSSL.
internal/renderer/renderer.go Registers bucket_policy as a self-executing partial template.
internal/handlers/policy_test.go Adds tests for canonicalJSON and detectPolicyType.
internal/handlers/buckets_handler.go Fetches policy + type in list/browser/settings; adds get/set policy handlers.
cmd/server/mocks_test.go Adds mocked GetBucketPolicy/SetBucketPolicy.
cmd/server/main.go Registers new bucket policy routes.
cmd/server/bucket_journey_test.go Updates mocks to account for policy lookups in journeys.

Comment on lines 223 to 233
<div class="space-y-4" x-data="{
policyType: '{{ .PolicyType }}',
customPolicy: '',
showEditor: {{ if eq .PolicyType "custom" }}true{{ else }}false{{ end }},
init() {
const el = this.$refs.policyData;
if (el && el.value) this.customPolicy = el.value;
}
}">
<textarea x-ref="policyData" class="hidden">{{ .FormattedPolicy }}</textarea>

Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bucket policy UI is duplicated inline here, while there is also a new reusable views/partials/bucket_policy.html fragment and a GET /buckets/:bucketName/policy handler. Keeping two copies increases the chance of UI drift and makes HTMX updates harder.

Consider loading the policy section the same way as the other settings cards (e.g., hx-get on load to render the bucket_policy partial) and removing the duplicated markup from this page.

Copilot uses AI. Check for mistakes.
Comment on lines 45 to 49
<form hx-post="/buckets/{{ .BucketName }}/policy" class="space-y-4 pt-4 border-t border-zinc-700">
<div>
<label class="block text-xs text-zinc-500 mb-2">Access Policy</label>
<div class="grid grid-cols-2 gap-2">
<label class="flex items-center gap-2 p-3 bg-zinc-800/50 rounded-lg cursor-pointer border border-transparent hover:border-zinc-600 transition-colors"
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This policy form has no hx-target/hx-swap. Since SetBucketPolicy returns the full bucket_policy fragment on errors, HTMX will replace only the <form> by default, leaving the rest of the component stale and potentially nesting fragments.

Add a stable wrapper (id/class) and set the form to target/swap that wrapper so the whole component updates together on both success and error paths.

Copilot uses AI. Check for mistakes.
Comment on lines +726 to +733
const url = '{{ .EndpointURL }}/{{ .BucketName }}/' + key;
this.directLinkURL = url;
this.directLinkDialogOpen = true;
this.$nextTick(() => lucide.createIcons());
},

copyDirectLinkToClipboard() {
navigator.clipboard.writeText(this.directLinkURL);
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

copyDirectLink builds a URL by string concatenation without URL-encoding the object key. Keys containing spaces, #, ?, or non-ASCII characters will produce invalid links.

Use proper URL construction/encoding (e.g., encode the key path segment) and consider handling the navigator.clipboard.writeText(...) promise to report failures (clipboard APIs often require HTTPS/permissions).

Suggested change
const url = '{{ .EndpointURL }}/{{ .BucketName }}/' + key;
this.directLinkURL = url;
this.directLinkDialogOpen = true;
this.$nextTick(() => lucide.createIcons());
},
copyDirectLinkToClipboard() {
navigator.clipboard.writeText(this.directLinkURL);
const encodedKey = encodeURIComponent(key);
const url = '{{ .EndpointURL }}/{{ .BucketName }}/' + encodedKey;
this.directLinkURL = url;
this.directLinkDialogOpen = true;
this.$nextTick(() => lucide.createIcons());
},
copyDirectLinkToClipboard() {
if (!navigator.clipboard || !navigator.clipboard.writeText) {
console.error('Clipboard API is not available in this browser/context.');
alert('Clipboard is not available. Please copy the link manually.');
return;
}
navigator.clipboard.writeText(this.directLinkURL)
.then(() => {
// Optionally, you could show a success notification here.
})
.catch((err) => {
console.error('Failed to copy direct link to clipboard:', err);
alert('Failed to copy link to clipboard. Please copy it manually.');
});

Copilot uses AI. Check for mistakes.

<body class="bg-background text-zinc-100 h-screen w-screen flex overflow-hidden" x-data="{ collapsed: false }"
hx-boost="true" hx-target="#main-content" hx-select="#main-content" hx-swap="outerHTML">
<body class="bg-background text-zinc-100 h-screen w-screen flex overflow-hidden" x-data="{ collapsed: false }">
Copy link

Copilot AI Feb 8, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing hx-boost/hx-target/hx-select/hx-swap from the <body> changes navigation behavior application-wide (links will no longer be boosted into #main-content). This appears unrelated to the bucket policy feature set and could regress UX/performance.

If this was intentional, consider keeping the boosted navigation (or replacing it with a narrower scope) and remove the now-redundant hx-boost="false" usage on the logout link; otherwise, revert this change to keep the PR scoped.

Copilot uses AI. Check for mistakes.
@damacus
Copy link
Owner

damacus commented Feb 8, 2026

Thanks for the PR. Ca ln you address the comments please. The main one I'm concerned about is squashing error codes.

@wilinz
Copy link
Author

wilinz commented Feb 10, 2026

image image image image image image

@damacus damacus changed the title ✨ feat(buckets/policy): add bucket policy UI, handlers, MinIO client methods, and tests feat(buckets/policy): add bucket policy UI, handlers, MinIO client methods, and tests Feb 10, 2026
@damacus
Copy link
Owner

damacus commented Feb 10, 2026

Amazing, thank you very much for this.

@damacus
Copy link
Owner

damacus commented Feb 10, 2026

Ping me when the tests are working! :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants